package org.example.supplychain.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;

/**
 * 监控信息导出器类，用于从指定端点获取监控信息并保存到文件中。
 * 即将通过Actuator方法暴露出的端点信息打印到文件中来监控系统运行情况
 *
 * 增加异常处理功能：
 * 可以检查系统是否故障；数据库是否连接；剩余磁盘空间是否可用；系统启动时间是否过长。
 */

@Component
public class MetricsExporterService {
    private final RestTemplate restTemplate;

    /**
     * 构造函数，用于注入 RestTemplate 对象。
     *
     * @param restTemplate RestTemplate 对象用于发送 HTTP 请求
     */
    @Autowired
    public MetricsExporterService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 将监控信息导出到文件中。
     */
    public void exportMetricsToFile() {
        // 获取 health 端点的内容
        ResponseEntity<String> healthResponse = restTemplate.getForEntity("http://localhost:8080/actuator/health", String.class);
        String healthData = "Health: " + healthResponse.getBody() + "\n";

        // 获取当前时间
        LocalDateTime currentTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String timestamp = "Time: " + currentTime.format(formatter) + "\n";

        // 获取 application.started.time 的内容
        ResponseEntity<String> startedTimeResponse = restTemplate.getForEntity("http://localhost:8080/actuator/metrics/application.started.time", String.class);
        String startedTimeData = startedTimeResponse.getBody();

        // 检查健康状态
        if (!isHealthStatusUp(healthData)) {
            throw new RuntimeException("Health status is not UP");
        }

        // 检查数据库连接状态
        if (!isDatabaseConnected(healthData)) {
            throw new RuntimeException("Database status is not UP");
        }

        // 解析磁盘剩余空间
        long freeDiskSpace = parseDiskFree(healthData);
        if (freeDiskSpace < 5 * 1024 * 1024 * 1024) { // 5GB in bytes
            throw new RuntimeException("Free disk space is less than 5GB");
        }

        // 解析应用启动时间
        double startupTime = parseStartupTime(startedTimeData);
        if (startupTime > 15.0) { // 如果启动时间超过15秒
            throw new RuntimeException("Application startup time is too long");
        }

        // 获取 metrics 端点的内容
        List<String> metrics = Arrays.asList(
                "application.ready.time",           // 应用准备就绪的时间
                "application.started.time",         // 应用启动的时间
                "disk.free",                        // 磁盘剩余空间
                "disk.total",                       // 磁盘总空间
                "executor.active",                  // 活跃的执行器线程数
                "executor.completed",               // 完成的任务数
                "executor.pool.core",               // 执行器核心线程池大小
                "executor.pool.max",                // 执行器最大线程池大小
                "executor.pool.size",               // 当前线程池大小
                "executor.queue.remaining",         // 执行器队列中剩余的容量
                "executor.queued",                  // 已入队的任务数
                "jvm.buffer.count",                 // JVM 缓冲区数量
                "jvm.buffer.memory.used",           // JVM 缓冲区已使用内存
                "jvm.buffer.total.capacity",        // JVM 缓冲区总容量
                "jvm.classes.loaded",               // 已加载的类数量
                "jvm.classes.unloaded",             // 已卸载的类数量
                "jvm.gc.live.data.size",            // JVM 垃圾回收后存活的数据大小
                "jvm.gc.max.data.size",             // JVM 垃圾回收的最大数据大小
                "jvm.gc.memory.allocated",          // 分配的 JVM 垃圾回收内存
                "jvm.gc.memory.promoted",           // 提升到老年代的内存
                "jvm.gc.overhead",                  // JVM 垃圾回收的开销
                "jvm.gc.pause",                     // JVM 垃圾回收暂停时间
                "jvm.memory.committed",             // JVM 已提交的内存
                "jvm.memory.max",                   // JVM 可用的最大内存
                "jvm.memory.usage.after.gc",        // JVM 垃圾回收后的内存使用情况
                "jvm.memory.used",                  // JVM 已使用的内存
                "jvm.threads.daemon",               // JVM 守护线程数
                "jvm.threads.live",                 // JVM 活跃线程数
                "jvm.threads.peak",                 // JVM 峰值线程数
                "jvm.threads.states",               // JVM 线程状态
                "logback.events",                   // Logback 事件数
                "process.cpu.usage",                // 进程 CPU 使用率
                "process.start.time",               // 进程启动时间
                "process.uptime",                   // 进程运行时间
                "system.cpu.count",                 // 系统 CPU 核心数
                "system.cpu.usage",                 // 系统 CPU 使用率
                "tomcat.sessions.active.current",   // 当前活跃的 Tomcat 会话数
                "tomcat.sessions.active.max",       // Tomcat 会话数的最大值
                "tomcat.sessions.alive.max",        // Tomcat 会话的最长存活时间
                "tomcat.sessions.created",          // 创建的 Tomcat 会话数
                "tomcat.sessions.expired",          // 过期的 Tomcat 会话数
                "tomcat.sessions.rejected"          // 被拒绝的 Tomcat 会话数
        );


        StringBuilder metricsData = new StringBuilder();
        metricsData.append(timestamp);
        metricsData.append(healthData);

        for (String metric : metrics) {
            String url = "http://localhost:8080/actuator/metrics/" + metric;
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            metricsData.append(metric).append(": ").append(response.getBody()).append("\n");
        }

        // 将监控信息追加到文件末尾
        try (FileWriter writer = new FileWriter("metrics.txt", true)) {
            writer.write(metricsData.toString());
            writer.write("\n"); // 添加一个空行，用于分隔不同时间点的监控信息
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isHealthStatusUp(String healthData) {
        return healthData.contains("\"status\":\"UP\"");
    }

    private boolean isDatabaseConnected(String healthData) {
        return healthData.contains("\"db\":{\"status\":\"UP\"");
    }


    private long parseDiskFree(String healthData) {
        int startIndex = healthData.indexOf("\"diskSpace\":{\"status\":\"UP\"");
        int endIndex = healthData.indexOf("}", startIndex);
        String diskSpaceData = healthData.substring(startIndex, endIndex);
        int freeIndex = diskSpaceData.indexOf("\"free\":");
        int thresholdIndex = diskSpaceData.indexOf("\"threshold\":");
        String freeString = diskSpaceData.substring(freeIndex + 7, thresholdIndex - 1);
        return Long.parseLong(freeString);
    }

    private long parseDiskTotal(String healthData) {
        int startIndex = healthData.indexOf("\"diskSpace\":{\"status\":\"UP\"");
        int endIndex = healthData.indexOf("}", startIndex);
        String diskSpaceData = healthData.substring(startIndex, endIndex);
        int totalIndex = diskSpaceData.indexOf("\"total\":");
        int freeIndex = diskSpaceData.indexOf("\"free\":");
        String totalString = diskSpaceData.substring(totalIndex + 8, freeIndex - 1);
        return Long.parseLong(totalString);
    }


    private double parseStartupTime(String startedTimeData) {
        int valueIndex = startedTimeData.indexOf("\"value\":");
        String timeString = startedTimeData.substring(valueIndex + 8, startedTimeData.indexOf("}"));
        return Double.parseDouble(timeString);
    }


    //以下4个函数用于系统运行状况界面使用

    //checkSystemStatus用于系统运行情况
    public String checkSystemStatus(String healthData) {
        if (isHealthStatusUp(healthData)) {
            return "正常";
        } else {
            return "故障";
        }
    }

    //checkDatabaseStatus用于数据库运行情况
    public String checkDatabaseStatus(String healthData) {
        if (isDatabaseConnected(healthData)) {
            return "正常";
        } else {
            return "故障";
        }
    }

    public String calculateDiskSpaceUsage(String healthData) {
        long totalSpace = parseDiskTotal(healthData);
        long freeSpace = parseDiskFree(healthData);
        double usedPercentage = ((double) (totalSpace - freeSpace) / totalSpace) * 100;
        return String.format("%.2f%%", usedPercentage);
    }

    //getSystemErrorCount用于当前系统出错数
    public int getSystemErrorCount() {
        return 0; // 直接返回当前系统错误数为0
    }
}
